/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package passwordchecker;

import interfaces.IPasswordChecker;
import rule.occurance.DigitOccuranceRule;
import rule.occurance.LowerCaseOccuranceRule;
import rule.occurance.UpperCaseOccuranceRule;
import rule.occurance.SpecialCharOccuranceRule;
import java.util.ArrayList;
import java.util.HashSet;
import rule.*;

/**
 *
 * @author Daniel Gribel
 */
public class NewPasswordChecker01 implements IPasswordChecker {
//    private int score;
//    private String result;
//    private ArrayList<NewRule> rules;
//    
//    public static final String VERY_WEAK = "very weak";
//    public static final String WEAK = "weak";
//    public static final String MEDIUM = "medium";
//    public static final String STRONG = "strong";
//    public static final String STRONGER = "stronger";
//    
//    public static final String[] classification = {VERY_WEAK, WEAK, MEDIUM, STRONG, STRONGER};
//    public static final int[] interval = {16, 25, 35, 45, Integer.MAX_VALUE};
//    
//    public NewPasswordChecker01() {
//        this.score = 0;
//        this.result = "";
//        this.rules = new ArrayList<NewRule>();
//        appendRules();
//    }
//
//    private void appendRules() {
//        
//        Clause atLeastOneLowerCase = new AtLeastOneLowerCaseChar();
//        Clause atLeastOneUpperCase = new AtLeastOneUpperCaseChar();
//        Clause atLeastOneNumber = new AtLeastOneNumber();
//        Clause atLeastOneSpecialChar = new AtLeastOneSpecialChar();
//        Clause atLeastThreeNumbers = new AtLeastThreeNumbers();
//        Clause length = new Length();
//        
//        ArrayList<Clause> c1 = new ArrayList<Clause>();
//        c1.add(atLeastOneLowerCase);
//        this.rules.add(new NewRule(c1));
//        
//        ArrayList<Clause> c2 = new ArrayList<Clause>();
//        c2.add(atLeastOneNumber);
//        this.rules.add(new NewRule(c2));
//        
//        ArrayList<Clause> c3 = new ArrayList<Clause>();
//        c3.add(atLeastOneSpecialChar);
//        this.rules.add(new NewRule(c3));
//        
//        ArrayList<Clause> c4 = new ArrayList<Clause>();
//        c4.add(atLeastOneLowerCase);
//        c4.add(atLeastOneUpperCase);
//        this.rules.add(new NewRule(c4));
//                
//        ArrayList<Clause> c5 = new ArrayList<Clause>();
//        c5.add(atLeastThreeNumbers);
//        this.rules.add(new NewRule(c5));
//        
//        ArrayList<Clause> c6 = new ArrayList<Clause>();
//        c6.add(length);
//        this.rules.add(new NewRule(c6));
//        
////        this.rules.add(new AlphaNumericAndSpecialChar());
////        this.rules.add(new AtLeastOneLowerCaseChar());
////        this.rules.add(new AtLeastOneNumber());
////        this.rules.add(new AtLeastOneSpecialChar());
////        this.rules.add(new AtLeastOneUpperCaseChar());
////        this.rules.add(new AtLeastThreeNumbers());
////        this.rules.add(new Length());
////        this.rules.add(new LettersAndNumbers());
////        this.rules.add(new UpperAndLowerCaseChars());
//    }
//    
//    public int getScore() {
//        return score;
//    }
//    
//    public String getResult() {
//        return result;
//    }
//    
//    public void checkPassword(String passwd) {
//        for(NewRule rule : this.rules) {
//            for(Clause clause : rule.getList()) {
//                if(clause.checkConditions(passwd))
//                    System.out.println(clause.outputMessage());
//                score = score + (int)clause.getScore();
//            }
//        }
//        result = classify();
//        printResult();
//    }
//    
//    private String classify() {
//        for(int i = 0; i < classification.length; i++) {
//            if(score < interval[i])
//                return classification[i];
//        }
//        return STRONGER;
//    }
//    
//    private void printResult() {
//        System.out.println("Final score: " + score);
//        System.out.println("Classification: " + result);
//    }
    
    private double score;
    private String result;
    private ArrayList<Clause> clauses;
    private RuleTypeAnd2 ruleAnd1;
    private RuleTypeAnd2 ruleAnd2;
    private RuleTypeAnd2 ruleAnd3;
    private RuleTypeAnd2 ruleAnd4;
    private RuleTypeAnd2 ruleAnd5;
    private RuleTypeAnd2 ruleAnd6;
    private RuleTypeAnd2 ruleAnd7;
    private RuleTypeOr ruleOr1;
    private ArrayList<NewRule> rulesList1;
    private ArrayList<NewRule> rulesList2;
    private RuleTypeCount ruleCount;
    private RuleValidator ruleValidator;
    private String password;
    
    
    public static final String VERY_WEAK = "very weak";
    public static final String WEAK = "weak";
    public static final String MEDIUM = "medium";
    public static final String STRONG = "strong";
    public static final String STRONGER = "stronger";
    
    public static final String[] classification = {VERY_WEAK, WEAK, MEDIUM, STRONG, STRONGER};
    public static final int[] interval = {16, 25, 35, 45, Integer.MAX_VALUE};
    
    public NewPasswordChecker01(String pass) {
        this.score = 0;
        this.result = "";
        //this.rules = new ArrayList<Rule>();
        password = pass;
        appendClauses();
        appendRules();
    }

    private void appendClauses(){
        clauses = new ArrayList<Clause>();
        this.clauses.add(0,new AtLeastOneLowerCaseChar(password));
        this.clauses.add(1,new AtLeastOneUpperCaseChar(password));
        this.clauses.add(2,new AtLeastOneNumber(password));
        this.clauses.add(3,new AtLeastOneSpecialChar(password));
        this.clauses.add(4,new AtLeastOneLowerCaseChar(password));
        this.clauses.add(5,new Length(password));
        
    }
    private void appendRules() {
        ArrayList<Clause> list = new ArrayList<Clause>();
        list.add(0,clauses.get(0));
        list.add(1,clauses.get(1));
        list.add(2,clauses.get(2));
        rulesList1 = new ArrayList();
        rulesList1 = new ArrayList(list);//AlphaNumericAndSpecialChar() -> validator
        
        list.clear();
        list.add(0,clauses.get(0));
        ruleAnd1 = new RuleTypeAnd2(list);//new AtLeastOneLowerCaseChar()
        
        list.clear();
        list.add(0,clauses.get(2));
        ruleAnd2 = new RuleTypeAnd2(list);//new AtLeastOneNumber()
        
        list.clear();
        list.add(0,clauses.get(3));
        ruleAnd3 = new RuleTypeAnd2(list);//new AtLeastOneSpecialChar()
        
        list.clear();
        list.add(0,clauses.get(1));
        ruleAnd4 = new RuleTypeAnd2(list);//new AtLeastOneUpperCaseChar()
        
        list.clear();
        list.add(0,clauses.get(2));
        ruleCount = new RuleTypeCount(list,3);//new AtLeastThreeNumbers()
        
        list.clear();
        list.add(0,clauses.get(0));
        list.add(1,clauses.get(1));
        ruleOr1 = new RuleTypeOr(list);
        list.clear();
        list.add(0,clauses.get(2));
        ruleAnd5 = new RuleTypeAnd2(list);
        rulesList2 = new ArrayList<NewRule>();
        rulesList2.add(ruleOr1);//new LettersAndNumbers()
        rulesList2.add(ruleAnd5);
    }
    
    public double getScore() {
        return score;
    }
    
    public String getResult() {
        return result;
    }
    
    public void simpleRules() {
        ArrayList <NewRule>simpleRules = new ArrayList<NewRule>();
        simpleRules.add(0,ruleAnd1);
        simpleRules.add(1,ruleAnd2);
        simpleRules.add(2,ruleAnd3);
        simpleRules.add(3,ruleAnd4);
        simpleRules.add(4,ruleCount);
        
        for(int i = 0; i < simpleRules.size(); i++) {
            if(simpleRules.get(i).ruleValue())
            {
                System.out.println(simpleRules.get(i).outputMessage());
                score = score + (int)simpleRules.get(i).getTotalPunctuation();
            }
        }
        
    }
    
    public void complexRules() {
//        ArrayList<ArrayList> complexRules = new ArrayList<ArrayList>();
//        complexRules.add(rulesList1);
//        complexRules.add(rulesList2);
        
        ruleValidator = new RuleValidator(rulesList1);
        if(ruleValidator.ruleValue())
        {
            System.out.println(ruleValidator.message());
            score = score + (int)ruleValidator.complexRuleScore();
        }
        
        ruleValidator = new RuleValidator(rulesList2);
        if(ruleValidator.ruleValue())
        {
            System.out.println(ruleValidator.message());
            score = score + (int)ruleValidator.complexRuleScore();
        }
       
    }
    
    public void checkPassword() {
        simpleRules();
        complexRules();
        result = classify();
        printResult();
        
    }
//        for(NewRule rule : this.rules) {
//            for(Clause clause : rule.getList()) {
//                if(clause.checkConditions(passwd))
//                    System.out.println(clause.outputMessage());
//                score = score + (int)clause.getScore();
//            }
//        }
        
    
//        for(NewRule rule : this.rules) {
//            for(Clause clause : rule.getList()) {
//                if(clause.checkConditions(passwd))
//                    System.out.println(clause.outputMessage());
//                score = score + (int)clause.getScore();
//            }
//        }
    
    private String classify() {
        for(int i = 0; i < classification.length; i++) {
            if(score < interval[i])
                return classification[i];
        }
        return STRONGER;
    }
    
    private void printResult() {
        System.out.println("Final score: " + score);
        System.out.println("Classification: " + result);
    }
}
